﻿using System;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace StarUtils.Extension
{
    public static class Encrypt
    {
        public static string DesKey = "#s^un2ye21fcv%|f0XpR,+vh";

        private static byte[] _iv;

        public static string AesKey = "QaP1AF8utIarcBqdhYTZpVGbiNQ9M6IL";

        private static byte[] Iv
        {
            get
            {
                if (_iv == null)
                {
                    int num = 16;
                    _iv = new byte[num];
                    for (int i = 0; i < num; i++)
                    {
                        _iv[i] = 0;
                    }
                }

                return _iv;
            }
        }

        public static string Md5By16(string value)
        {
            return Md5By16(value, Encoding.UTF8);
        }

        public static string Md5By16(string value, Encoding encoding)
        {
            return Md5(value, encoding, 4, 8);
        }

        public static string Md5By32(string value)
        {
            return Md5By32(value, Encoding.UTF8);
        }

        public static string Md5By32(string value, Encoding encoding)
        {
            return Md5(value, encoding, null, null);
        }

        private static string Md5(string value, Encoding encoding, int? startIndex, int? length)
        {
            if (string.IsNullOrWhiteSpace(value))
            {
                return string.Empty;
            }

            MD5CryptoServiceProvider mD5CryptoServiceProvider = new MD5CryptoServiceProvider();
            string text;
            try
            {
                byte[] array = mD5CryptoServiceProvider.ComputeHash(encoding.GetBytes(value));
                text = ((!startIndex.HasValue) ? BitConverter.ToString(array) : BitConverter.ToString(array, startIndex.SafeValue(), length.SafeValue()));
            }
            finally
            {
                mD5CryptoServiceProvider.Clear();
            }

            return text.Replace("-", "");
        }

        public static string DesEncrypt(object value)
        {
            return DesEncrypt(value, DesKey);
        }

        public static string DesEncrypt(object value, string key)
        {
            return DesEncrypt(value, key, Encoding.UTF8);
        }

        public static string DesEncrypt(object value, string key, Encoding encoding)
        {
            string text = value.SafeString();
            if (!ValidateDes(text, key))
            {
                return string.Empty;
            }

            using ICryptoTransform transform = CreateDesProvider(key).CreateEncryptor();
            return GetEncryptResult(text, encoding, transform);
        }

        private static bool ValidateDes(string text, string key)
        {
            if (string.IsNullOrWhiteSpace(text) || string.IsNullOrWhiteSpace(key))
            {
                return false;
            }

            return key.Length == 24;
        }

        private static TripleDESCryptoServiceProvider CreateDesProvider(string key)
        {
            return new TripleDESCryptoServiceProvider
            {
                Key = Encoding.ASCII.GetBytes(key),
                Mode = CipherMode.ECB,
                Padding = PaddingMode.PKCS7
            };
        }

        private static string GetEncryptResult(string value, Encoding encoding, ICryptoTransform transform)
        {
            byte[] bytes = encoding.GetBytes(value);
            return Convert.ToBase64String(transform.TransformFinalBlock(bytes, 0, bytes.Length));
        }

        public static string DesDecrypt(object value)
        {
            return DesDecrypt(value, DesKey);
        }

        public static string DesDecrypt(object value, string key)
        {
            return DesDecrypt(value, key, Encoding.UTF8);
        }

        public static string DesDecrypt(object value, string key, Encoding encoding)
        {
            string text = value.SafeString();
            if (!ValidateDes(text, key))
            {
                return string.Empty;
            }

            using ICryptoTransform transform = CreateDesProvider(key).CreateDecryptor();
            return GetDecryptResult(text, encoding, transform);
        }

        private static string GetDecryptResult(string value, Encoding encoding, ICryptoTransform transform)
        {
            byte[] array = Convert.FromBase64String(value);
            byte[] bytes = transform.TransformFinalBlock(array, 0, array.Length);
            return encoding.GetString(bytes);
        }

        public static string AesEncrypt(string value)
        {
            return AesEncrypt(value, AesKey);
        }

        public static string AesEncrypt(string value, string key)
        {
            return AesEncrypt(value, key, Encoding.UTF8);
        }

        public static string AesEncrypt(string value, string key, Encoding encoding)
        {
            if (string.IsNullOrWhiteSpace(value) || string.IsNullOrWhiteSpace(key))
            {
                return string.Empty;
            }

            RijndaelManaged rijndaelManaged = CreateRijndaelManaged(key);
            using ICryptoTransform transform = rijndaelManaged.CreateEncryptor(rijndaelManaged.Key, rijndaelManaged.IV);
            return GetEncryptResult(value, encoding, transform);
        }

        private static RijndaelManaged CreateRijndaelManaged(string key)
        {
            return new RijndaelManaged
            {
                Key = Convert.FromBase64String(key),
                Mode = CipherMode.CBC,
                Padding = PaddingMode.PKCS7,
                IV = Iv
            };
        }

        public static string AesDecrypt(string value)
        {
            return AesDecrypt(value, AesKey);
        }

        public static string AesDecrypt(string value, string key)
        {
            return AesDecrypt(value, key, Encoding.UTF8);
        }

        public static string AesDecrypt(string value, string key, Encoding encoding)
        {
            if (string.IsNullOrWhiteSpace(value) || string.IsNullOrWhiteSpace(key))
            {
                return string.Empty;
            }

            RijndaelManaged rijndaelManaged = CreateRijndaelManaged(key);
            using ICryptoTransform transform = rijndaelManaged.CreateDecryptor(rijndaelManaged.Key, rijndaelManaged.IV);
            return GetDecryptResult(value, encoding, transform);
        }

        public static string HmacMd5(string value, string key)
        {
            return HmacMd5(value, key, Encoding.UTF8);
        }

        public static string HmacMd5(string value, string key, Encoding encoding)
        {
            if (string.IsNullOrWhiteSpace(value) || string.IsNullOrWhiteSpace(key))
            {
                return string.Empty;
            }

            byte[] source = new HMACMD5(encoding.GetBytes(key)).ComputeHash(encoding.GetBytes(value));
            return string.Join("", (from x in source.ToList()
                                    select x.ToString("x2")).ToArray());
        }

        public static string HmacSha1(string value, string key)
        {
            return HmacSha1(value, key, Encoding.UTF8);
        }

        public static string HmacSha1(string value, string key, Encoding encoding)
        {
            if (string.IsNullOrWhiteSpace(value) || string.IsNullOrWhiteSpace(key))
            {
                return string.Empty;
            }

            byte[] source = new HMACSHA1(encoding.GetBytes(key)).ComputeHash(encoding.GetBytes(value));
            return string.Join("", (from x in source.ToList()
                                    select x.ToString("x2")).ToArray());
        }

        public static string HmacSha256(string value, string key)
        {
            return HmacSha256(value, key, Encoding.UTF8);
        }

        public static string HmacSha256(string value, string key, Encoding encoding)
        {
            if (string.IsNullOrWhiteSpace(value) || string.IsNullOrWhiteSpace(key))
            {
                return string.Empty;
            }

            byte[] source = new HMACSHA256(encoding.GetBytes(key)).ComputeHash(encoding.GetBytes(value));
            return string.Join("", (from x in source.ToList()
                                    select x.ToString("x2")).ToArray());
        }

        public static string HmacSha384(string value, string key)
        {
            return HmacSha384(value, key, Encoding.UTF8);
        }

        public static string HmacSha384(string value, string key, Encoding encoding)
        {
            if (string.IsNullOrWhiteSpace(value) || string.IsNullOrWhiteSpace(key))
            {
                return string.Empty;
            }

            byte[] source = new HMACSHA384(encoding.GetBytes(key)).ComputeHash(encoding.GetBytes(value));
            return string.Join("", (from x in source.ToList()
                                    select x.ToString("x2")).ToArray());
        }

        public static string HmacSha512(string value, string key)
        {
            return HmacSha512(value, key, Encoding.UTF8);
        }

        public static string HmacSha512(string value, string key, Encoding encoding)
        {
            if (string.IsNullOrWhiteSpace(value) || string.IsNullOrWhiteSpace(key))
            {
                return string.Empty;
            }

            byte[] source = new HMACSHA512(encoding.GetBytes(key)).ComputeHash(encoding.GetBytes(value));
            return string.Join("", (from x in source.ToList()
                                    select x.ToString("x2")).ToArray());
        }

        public static string Sha1(string value)
        {
            return Sha1(value, Encoding.UTF8);
        }

        public static string Sha1(string value, Encoding encoding)
        {
            if (string.IsNullOrWhiteSpace(value))
            {
                return string.Empty;
            }

            using SHA1 sHA = SHA1.Create();
            byte[] source = sHA.ComputeHash(encoding.GetBytes(value));
            return string.Join("", (from x in source.ToList()
                                    select x.ToString("x2")).ToArray());
        }

        public static string Sha256(string value)
        {
            return Sha256(value, Encoding.UTF8);
        }

        public static string Sha256(string value, Encoding encoding)
        {
            if (string.IsNullOrWhiteSpace(value))
            {
                return string.Empty;
            }

            using SHA256 sHA = SHA256.Create();
            byte[] source = sHA.ComputeHash(encoding.GetBytes(value));
            return string.Join("", (from x in source.ToList()
                                    select x.ToString("x2")).ToArray());
        }

        public static string Sha384(string value)
        {
            return Sha384(value, Encoding.UTF8);
        }

        public static string Sha384(string value, Encoding encoding)
        {
            if (string.IsNullOrWhiteSpace(value))
            {
                return string.Empty;
            }

            using SHA384 sHA = SHA384.Create();
            byte[] source = sHA.ComputeHash(encoding.GetBytes(value));
            return string.Join("", (from x in source.ToList()
                                    select x.ToString("x2")).ToArray());
        }

        public static string Sha512(string value)
        {
            return Sha512(value, Encoding.UTF8);
        }

        public static string Sha512(string value, Encoding encoding)
        {
            if (string.IsNullOrWhiteSpace(value))
            {
                return string.Empty;
            }

            using SHA512 sHA = SHA512.Create();
            byte[] source = sHA.ComputeHash(encoding.GetBytes(value));
            return string.Join("", (from x in source.ToList()
                                    select x.ToString("x2")).ToArray());
        }

        public static string Base64Encrypt(string value)
        {
            return Base64Encrypt(value, Encoding.UTF8);
        }

        public static string Base64Encrypt(string value, Encoding encoding)
        {
            if (!string.IsNullOrWhiteSpace(value))
            {
                return Convert.ToBase64String(encoding.GetBytes(value));
            }

            return string.Empty;
        }

        public static string Base64Decrypt(string value)
        {
            return Base64Decrypt(value, Encoding.UTF8);
        }

        public static string Base64Decrypt(string value, Encoding encoding)
        {
            if (!string.IsNullOrWhiteSpace(value))
            {
                return encoding.GetString(Convert.FromBase64String(value));
            }

            return string.Empty;
        }
    }
}
